package edu.jxufe.nb112.plugin;

import edu.jxufe.nb112.common.code.io.FileUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.filefilter.OrFileFilter;
import org.apache.commons.io.filefilter.RegexFileFilter;
import org.apache.commons.lang3.StringUtils;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;

import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Mojo(name = "drive")
public class TestMojo extends AbstractMojo {

    @Parameter
    private Properties fileProperties;
    @Parameter
    private Properties ELProperties;

    Map<String, List<String>> config = new HashMap<String, List<String>>();

    Map<String, File> fileSource = new HashMap<String, File>();

    List<File> targetFileList = new ArrayList<File>();

    private void init() {
        Iterator<Map.Entry<Object, Object>> it = fileProperties.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<Object, Object> entry = it.next();
            String key = (String) entry.getKey();
            File file = new File(key);
            if (file.exists()) {
                List<String> expressList = config.get(key);
                if (expressList == null) {
                    expressList = new ArrayList<String>();
                    config.put(key, expressList);
                }
                String value = (String) entry.getValue();
                if (StringUtils.isNotEmpty(value) && !expressList.contains(value)) {
                    fileSource.put(key, file);
                    expressList.add(value);
                }
            }
        }
    }

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        init();
        Iterator<Map.Entry<String, File>> it = fileSource.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<String, File> entry = it.next();
            String fileName = entry.getKey();
            File file = entry.getValue();
            List<String> expressList = config.get(fileName);
            Iterator<String> expressIt = expressList.iterator();
            OrFileFilter orFileFilter = new OrFileFilter();
            while (expressIt.hasNext()) {
                RegexFileFilter regexFileFilter = new RegexFileFilter(expressIt.next());
                orFileFilter.addFileFilter(regexFileFilter);
            }
            targetFileList.addAll(FileUtils.listAllFiles(file, orFileFilter));
        }
        for (File file : targetFileList) {
            try {
                String staticMd5Context = makeStaticTagMD5(file, ELProperties);
                FileWriter writer = new FileWriter(file, false);
                writer.write(staticMd5Context);
                writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public String makeStaticTagMD5(File file, Properties ELProperties) throws IOException {
        StringBuffer resultBuffer = new StringBuffer();
        InputStream in = null;
        try {
            in = new FileInputStream(file);
            getLog().debug("-----------------------------------------------");
            getLog().info("文件：" + file.getAbsolutePath());
            String context = IOUtils.toString(in);
            //匹配 link和script 标签
            String searchTagPatternStr = "(?<!<[!%]?--[%]?[>]?)<[\\s]*(link|script)[\\s\\S]*?/?[\\s]*[>]+?";
            Pattern searchTagPattern = Pattern.compile(searchTagPatternStr, Pattern.MULTILINE);

            //匹配 href和src
            String hrefPatternStr = "(?<=(href|src)=\")[^\"]*?(?=\")";
            Pattern hrefPattern = Pattern.compile(hrefPatternStr, Pattern.MULTILINE);

            Matcher searchTagMatcher = searchTagPattern.matcher(context);
            while (searchTagMatcher.find()) {
                getLog().debug(">>>>>>--------------------------------------");
                getLog().debug("查找到" + searchTagMatcher.group(1) + "标签: " + searchTagMatcher.group());
                int end = searchTagMatcher.end(), beg = searchTagMatcher.start();
                String staticTag = context.substring(beg, end);
                if (!isCommentBlock(context, "<!--", "-->", beg, end) && !isCommentBlock(context, "<%--", "--%>", beg, end)) {
                    Matcher hrefMatcher = hrefPattern.matcher(staticTag);
                    if (hrefMatcher.find()) {
                        getLog().debug("提取到链接" + hrefMatcher.group(1) + "  => " + hrefMatcher.group());
                        String href = hrefMatcher.group().trim();
                        if (!href.startsWith("http") && !href.startsWith("HTTP")) {
                            String replaceELHref = reaplaceEL(ELProperties, hrefMatcher.group()).trim();
                            int paramIndex = replaceELHref.indexOf("?");
                            if(paramIndex>0){
                                replaceELHref = replaceELHref.substring(0,paramIndex);
                            }
                            getLog().info("链接文件路径：" + replaceELHref);
                            File linkFile = new File(replaceELHref);
                            if (linkFile.exists()) {
                                try {
                                    String md5 = DigestUtils.md5Hex(new FileInputStream(linkFile));
                                    getLog().info("提取文件特征MD5：" + md5);
                                    int idx = href.indexOf('?');
                                    if (idx < 0) {
                                        href = href + "?" + md5;
                                    } else {
                                        href = href.substring(0, idx) + '?' + md5;
                                    }
                                    StringBuffer sb = new StringBuffer();
                                    hrefMatcher.appendReplacement(sb, href.replaceAll("\\$", "\\\\\\$"));  //将替换后的子串以及其之前到上次匹配子串之后的字符串段添加到一个StringBuffer对象里。
                                    hrefMatcher.appendTail(sb);
                                    getLog().info(sb);
                                    searchTagMatcher.appendReplacement(resultBuffer, sb.toString().replaceAll("\\$", "\\\\\\$"));

                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                            } else {
                                getLog().warn(linkFile.getAbsoluteFile() + "文件不存在");
                            }
                        }
                    }
                } else {
                    getLog().debug("该标签被注释");
                }
                getLog().debug("<<<<<--------------------------------------");
            }
            searchTagMatcher.appendTail(resultBuffer);
            getLog().debug("结果：----------------------------->");
            getLog().debug(resultBuffer);
            getLog().debug("------------------------------------------------------");
        } catch (FileNotFoundException e) {
            throw e;
        } catch (IOException e) {
            throw e;
        } finally {
            IOUtils.closeQuietly(in);

        }
        return resultBuffer.toString();
    }

    /**
     * str子串begin,end是否是注释
     *
     * @param str
     * @param openComment  注释开始标记
     * @param closeComment 注释结束标记
     * @param begin        子串开始下标
     * @param end          子串结束下标
     * @return
     */
    public static boolean isCommentBlock(String str, String openComment, String closeComment, int begin, int end) {
        int bc = str.lastIndexOf(openComment, begin);
        int ec = str.lastIndexOf(closeComment, begin);
        if (bc == -1) {
            //System.out.println("无注释ok");
            return false;
        } else {
            if (ec == -1) {
                //System.out.println("无注释ok");
                return false;

            } else {
                if (bc > ec) {
                    return true;
                    /*
                    int suec = str.indexOf("-->",end);
                    if(suec==-1){
                        //System.out.println("注释错误漏掉-->");
                        return true;
                    }else {
                        //System.out.println("被注释" + str.substring(bc, suec + 3));
                        return true;
                    }*/
                } else {
                    //System.out.println("其他注释ok:"+str.substring(bc, ec+3));
                    return false;
                }
            }
        }
    }

    /**
     * 替换掉el表达式的值
     *
     * @param ELProperties
     * @param str
     * @return
     */
    public static String reaplaceEL(Properties ELProperties, String str) {
        Set<Map.Entry<Object, Object>> entrySet = ELProperties.entrySet();
        Iterator<Map.Entry<Object, Object>> it = entrySet.iterator();
        while (it.hasNext()) {
            Map.Entry<Object, Object> entry = it.next();
            str = str.replaceAll("\\$\\{.*?" + entry.getKey() + ".*?\\}", entry.getValue().toString().replaceAll("\\$", "\\\\\\$").replaceAll("\\\\", "/"));
        }
        return str;
    }


}
